﻿/**************************************************************
 *
 * 唯一标识：ab23e4f8-e429-40a4-bd9a-764c232c53ce
 * 命名空间：MediatR.Behaviors
 * 创建时间：2023/8/18 9:34:10
 * 机器名称：DESKTOP-S0D075D
 * 创建者：antho
 * 电子邮箱：fengqinhua2016@163.com
 * 描述：
 *
 **************************************************************/

using MediatR;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Sgr.Domain.Uow;
using Sgr.EntityFrameworkCore;
using Sgr.Exceptions;
using Sgr.Utilities;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Net.Cache;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;

namespace Sgr.MediatR.Behaviors
{
    /// <summary>
    /// MediatR事务处理行为管道
    /// </summary>
    /// <remarks>
    /// 该管道用于自动处理Command和Query的数据库事务，主要功能：
    /// 1. 自动开启和管理事务
    /// 2. 异常处理和事务回滚
    /// 3. 支持事务嵌套（优先使用已存在的事务）
    /// 4. 支持通过特性配置事务行为
    /// </remarks>
    public class TransactionBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
        where TRequest : IRequest<TResponse> //, IRequireUnitOfWork
    {
        private readonly IUnitOfWorkManager _unitOfWorkManager;
        private readonly ILogger<TransactionBehavior<TRequest, TResponse>> _logger;

        public TransactionBehavior(
            IUnitOfWorkManager unitOfWorkManager,
            ILogger<TransactionBehavior<TRequest, TResponse>> logger)
        {
            _unitOfWorkManager = unitOfWorkManager ?? throw new ArgumentNullException(nameof(unitOfWorkManager));
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
        }

        /// <summary>
        /// 处理请求并管理事务
        /// </summary>
        /// <param name="request">请求对象</param>
        /// <param name="next">请求处理委托</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>处理结果</returns>
        public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken)
        {
            // 仅在请求实现 IRequireUnitOfWork 时才启用事务逻辑，避免开放泛型注册时 DI 解析失败
            if (request is not IRequireUnitOfWork)
                return await next();

            // 如果已存在工作单元，则直接使用现有事务上下文
            if (_unitOfWorkManager.Current != null)
                return await next();

            // 获取工作单元配置
            var attribute = UnitOfWorkHelper.GetUnitOfWorkAttribute(typeof(TRequest));

            //如果请求被禁用，则直接跳过
            if (attribute != null && attribute.IsDisabled)
                return await next();

            //  获取工作单元选项
            UnitOfWorkOption option = new UnitOfWorkOption()
            {
                IsTransactional = true
            };

            attribute?.SetOptions(option);

            // 开启工作单元
            using (var uow = _unitOfWorkManager.Begin(option))
            {
                try
                {
                    var response = await next();

                    await uow.CommitAsync(cancellationToken);

                    return response;
                }
                catch
                {
                    await uow.RollbackAsync(cancellationToken);

                    _logger.LogError($"工作单元 {uow.Id} 执行失败并已回滚, 请求类型: {typeof(TRequest).Name}");

                    throw;
                }
            }
        }
    }
}